package com.yonyou.pmclouds.im.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyou.pmclouds.basecom.conf.HttpClientProperties;
import com.yonyou.pmclouds.im.entity.IMExceptionResultVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @Description: http请求发送类（IM相关）
 * 之所以没有提取公共类里，是因为IM服务端将异常码返回到http请求的状态码中，
 * 需要根据此异常码来确定下一步操作（例如：状态码为401时，token失效需要重新获取token）
 * 与customer端的HttpTooKit不同处在于doPostWithJson方法,返回状态异常时，包装了一个异常结果集，而并非原来的跑出runtime异常
*
* @author: zhangwce
* @Date: 2018/4/17
*/
public class IMHttpTookit {
    private static Logger logger = LoggerFactory.getLogger(IMHttpTookit.class);
    private static final CloseableHttpClient httpClient;
    public static final String CHARSET = "UTF-8";
    private static int timeout = 360000;
    private static boolean needRetry = false;
    private static HttpClientProperties properties = new HttpClientProperties();
    private static ObjectMapper mapper = new ObjectMapper();
    public IMHttpTookit() {
    }

    public static boolean initParms() {
        return true;
    }

    public static String doGet(String url, Map<String, String> params) {
        return doGet(url, params, null, "UTF-8");
    }

    public static String doPost(String url, Map<String, String> params) {
        return doPost(url, params, null, "UTF-8");
    }

    public static String doDelete(String url, Map<String, String> params) {
        return doDelete(url, params, null, "UTF-8");
    }

    public static String doPut(String url, Map<String, String> params) {
        return doPut(url, params, null, "UTF-8");
    }

    public static String doGet(String url, Map<String, String> params, Map<String, String> headers) {
        return doGet(url, params, headers, "UTF-8");
    }

    public static String doPost(String url, Map<String, String> params, Map<String, String> headers) {
        return doPost(url, params, headers, "UTF-8");
    }

    public static String doDelete(String url, Map<String, String> params, Map<String, String> headers) {
        return doDelete(url, params, headers, "UTF-8");
    }

    public static String doPostWithJson(String url, String json, Map<String, String> headers) {
        return doPostWithJson(url, json, headers, "UTF-8");
    }

    public static String doPut(String url, Map<String, String> params, Map<String, String> headers) {
        return doPut(url, params, headers, "UTF-8");
    }

//    public static String doPostFile(String url, Map<String, String> params, Map<String, String> headers, String filepath) {
//        return doPostFile(url, params, headers, filepath, "UTF-8");
//    }

    public static String doGet(String url, Map<String, String> params, Map<String, String> headers, String charset) {
        if (StringUtils.isBlank(url)) {
            return null;
        } else {
            try {
                Iterator i$;
                Entry entry;
                if (params != null && !params.isEmpty()) {
                    List<NameValuePair> pairs = new ArrayList(params.size());
                    i$ = params.entrySet().iterator();

                    while(i$.hasNext()) {
                        entry = (Entry)i$.next();
                        String value = (String)entry.getValue();
                        if (value != null) {
                            pairs.add(new BasicNameValuePair((String)entry.getKey(), value));
                        }
                    }

                    url = url + "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
                }

                HttpGet httpGet = new HttpGet(url);
                if (headers != null && !headers.isEmpty()) {
                    i$ = headers.entrySet().iterator();

                    while(i$.hasNext()) {
                        entry = (Entry)i$.next();
                        httpGet.addHeader((String)entry.getKey(), (String)entry.getValue());
                    }
                }

                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httpGet.setConfig(requestConfig);
                entry = null;

                CloseableHttpResponse response;
                try {
                    response = httpClient.execute(httpGet);
                } catch (HttpHostConnectException | ConnectTimeoutException var10) {
                    logger.error("connect timeout, will reconnect", var10);
                    response = httpClient.execute(httpGet);
                }

                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    httpGet.abort();
                    throw new RuntimeException("HttpClient,error status code :" + statusCode);
                } else {
                    HttpEntity entity = response.getEntity();
                    String result = null;
                    if (entity != null) {
                        result = EntityUtils.toString(entity, "utf-8");
                    }

                    EntityUtils.consume(entity);
                    response.close();
                    httpGet.releaseConnection();
                    return result;
                }
            } catch (Exception var11) {
                logger.error("Exception e " + var11.getMessage(), var11);
                return null;
            }
        }
    }

    static {
        String maxTotal = IMHttpTookit.properties.getMaxTotal();
        String maxPerRoute = IMHttpTookit.properties.getMaxPerRoute();
        if (maxTotal == null) {
            maxTotal = "100";
        }

        if (maxPerRoute == null) {
            maxPerRoute = "100";
        }

        String timeOut = IMHttpTookit.properties.getTimeOut();
        if (timeOut != null) {
            try {
                timeout = Integer.valueOf(timeOut);
                if (timeout > 500) {
                    timeout = 500;
                }

                timeout *= 1000;
            } catch (Exception var8) {
                logger.error("Exception e " + var8.getMessage(), var8);
            }
        }

        RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout).setSocketTimeout(timeout).build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(Integer.valueOf(maxTotal));
        cm.setDefaultMaxPerRoute(Integer.valueOf(maxPerRoute));
        String retryStr = IMHttpTookit.properties.getNeedretry();
        if (retryStr != null) {
            needRetry = Boolean.valueOf(retryStr);
        }

        if (needRetry) {
            httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).setConnectionManager(cm).setRetryHandler(new DefaultHttpRequestRetryHandler(3, false)).build();
        } else {
            httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).setConnectionManager(cm).build();
        }

    }

//    public static String doPostFile(String url, Map<String, String> params, Map<String, String> headers, String filepath, String charset) {
//        if (StringUtils.isBlank(url)) {
//            return null;
//        } else {
//            try {
//                FileBody bin = new FileBody(new File(filepath));
//                MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//                builder.addPart("file", bin);
//                HttpPost httpPost = new HttpPost(url);
//                httpPost.setEntity(builder.build());
//                if (headers != null && !headers.isEmpty()) {
//                    Iterator i$ = headers.entrySet().iterator();
//
//                    while(i$.hasNext()) {
//                        Entry<String, String> entry = (Entry)i$.next();
//                        httpPost.addHeader((String)entry.getKey(), (String)entry.getValue());
//                    }
//                }
//
//                HttpResponse response = httpClient.execute(httpPost);
//                int statusCode = response.getStatusLine().getStatusCode();
//                if (statusCode != 200) {
//                    httpPost.abort();
//                    throw new RuntimeException("HttpClient,error status code :" + statusCode);
//                } else {
//                    HttpEntity entity = response.getEntity();
//                    String result = null;
//                    if (entity != null) {
//                        result = EntityUtils.toString(entity, "utf-8");
//                    }
//
//                    EntityUtils.consume(entity);
//                    httpPost.releaseConnection();
//                    return result;
//                }
//            } catch (Exception var12) {
//                logger.error("Exception e " + var12.getMessage(), var12);
//                return null;
//            }
//        }
//    }

    public static String doPost(String url, Map<String, String> params, Map<String, String> headers, String charset) {
        if (StringUtils.isBlank(url)) {
            return null;
        } else {
            try {
                List<NameValuePair> pairs = null;
                if (params != null && !params.isEmpty()) {
                    pairs = new ArrayList<>(params.size());

                    for (Entry<String, String> o : params.entrySet()) {
                        String value = o.getValue();
                        if (StringUtils.isNotBlank(value)) {
                            pairs.add(new BasicNameValuePair(o.getKey(), value));
                        }
                    }
                }

                HttpPost httpPost = new HttpPost(url);
                if (pairs != null && pairs.size() > 0) {
                    httpPost.setEntity(new UrlEncodedFormEntity(pairs, "UTF-8"));
                }

                if (headers != null && !headers.isEmpty()) {

                    for (Entry<String, String> o : headers.entrySet()) {
                        httpPost.addHeader(o.getKey(), o.getValue());
                    }
                }

                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httpPost.setConfig(requestConfig);
                CloseableHttpResponse response = httpClient.execute(httpPost);
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    httpPost.abort();
                    throw new RuntimeException("HttpClient,error status code :" + statusCode);
                } else {
                    HttpEntity entity = response.getEntity();
                    String result = null;
                    if (entity != null) {
                        result = EntityUtils.toString(entity, "utf-8");
                    }

                    EntityUtils.consume(entity);
                    response.close();
                    httpPost.releaseConnection();
                    return result;
                }
            } catch (Exception var11) {
                logger.error("Exception e " + var11.getMessage(), var11);
                return null;
            }
        }
    }

    public static String doPostWithJson(String url, String json, Map<String, String> headers, String charset) {
        if (StringUtils.isBlank(url)) {
            return null;
        } else {
            try {
                HttpPost httpPost = new HttpPost(url);
                if (headers != null && !headers.isEmpty()) {
                    for (Entry<String, String> o : headers.entrySet()) {
                        httpPost.addHeader(o.getKey(), o.getValue());
                    }
                }

                StringEntity s = new StringEntity(json, "UTF-8");
                s.setContentEncoding("UTF-8");
                s.setContentType("application/json");
                httpPost.setEntity(s);
                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httpPost.setConfig(requestConfig);
                CloseableHttpResponse response = httpClient.execute(httpPost);
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    httpPost.abort();
                    //throw new RuntimeException("HttpClient,error status code :" + statusCode);
                    IMExceptionResultVO imExceptionResultVO = new IMExceptionResultVO();
                    imExceptionResultVO.setResponseCode(statusCode);
                    imExceptionResultVO.setResponseMsg("HttpClient,error status code :" + statusCode);

                    return mapper.writeValueAsString(imExceptionResultVO);
                } else {
                    HttpEntity entity = response.getEntity();
                    String result = null;
                    if (entity != null) {
                        result = EntityUtils.toString(entity, "utf-8");
                    }

                    EntityUtils.consume(entity);
                    response.close();
                    httpPost.releaseConnection();
                    return result;
                }
            } catch (Exception var11) {
                logger.error("Exception e " + var11.getMessage(), var11);
                return null;
            }
        }
    }

    public static String doDelete(String url, Map<String, String> params, Map<String, String> headers, String charset) {
        if (StringUtils.isBlank(url)) {
            return null;
        } else {
            try {

                if (params != null && !params.isEmpty()) {
                    List<NameValuePair> pairs = new ArrayList<>(params.size());
                    Iterator i$;
                    Entry entry;
                    i$ = params.entrySet().iterator();
                    while(i$.hasNext()) {
                        entry = (Entry)i$.next();
                        String value = (String)entry.getValue();
                        if (value != null) {
                            pairs.add(new BasicNameValuePair((String)entry.getKey(), value));
                        }
                    }

                    url = url + "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
                }

                HttpDelete httpDelete = new HttpDelete(url);
                if (headers != null && !headers.isEmpty()) {
                    Iterator i$;
                    Entry entry;
                    i$ = headers.entrySet().iterator();

                    while(i$.hasNext()) {
                        entry = (Entry)i$.next();
                        httpDelete.addHeader((String)entry.getKey(), (String)entry.getValue());
                    }
                }

                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httpDelete.setConfig(requestConfig);
                CloseableHttpResponse response = httpClient.execute(httpDelete);
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    httpDelete.abort();
                    throw new RuntimeException("HttpClient,error status code :" + statusCode);
                } else {
                    HttpEntity entity = response.getEntity();
                    String result = null;
                    if (entity != null) {
                        result = EntityUtils.toString(entity, "utf-8");
                    }

                    EntityUtils.consume(entity);
                    response.close();
                    httpDelete.releaseConnection();
                    return result;
                }
            } catch (Exception var10) {
                logger.error("Exception e " + var10.getMessage(), var10);
                return null;
            }
        }
    }

    public static void setProperties(HttpClientProperties properties) {
        IMHttpTookit.properties = properties;
    }

    public static String doPut(String url, Map<String, String> params, Map<String, String> headers, String charset) {
        if (StringUtils.isBlank(url)) {
            return null;
        } else {
            try {
                List<NameValuePair> pairs = null;
                if (params != null && !params.isEmpty()) {
                    pairs = new ArrayList<>(params.size());

                    for (Entry<String, String> entry : params.entrySet()) {
                        String value = entry.getValue();
                        if (value != null) {
                            pairs.add(new BasicNameValuePair(entry.getKey(), value));
                        }
                    }
                }

                HttpPut httpPut = new HttpPut(url);
                if (pairs != null && pairs.size() > 0) {
                    httpPut.setEntity(new UrlEncodedFormEntity(pairs, "UTF-8"));
                }

                if (headers != null && !headers.isEmpty()) {

                    for (Entry<String, String> entry : headers.entrySet()) {
                        httpPut.addHeader(entry.getKey(), entry.getValue());
                    }
                }

                CloseableHttpResponse response = httpClient.execute(httpPut);
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    httpPut.abort();
                    throw new RuntimeException("HttpClient,error status code :" + statusCode);
                } else {
                    HttpEntity entity = response.getEntity();
                    String result = null;
                    if (entity != null) {
                        result = EntityUtils.toString(entity, "utf-8");
                    }

                    EntityUtils.consume(entity);
                    response.close();
                    httpPut.releaseConnection();
                    return result;
                }
            } catch (Exception var10) {
                logger.error("Exception e " + var10.getMessage(), var10);
                return null;
            }
        }
    }
}
